package com.zhaoc.ioc;

import java.io.File;
import com.zhaoc.ioc.container.ApplicationContext;
import com.zhaoc.ioc.container.ScopeTypeEnum;
import com.zhaoc.ioc.container.XmlApplicationContext;
/** 
 * <br>类 名: ParseBasePackage
 * <br>描 述: 自动扫描包，并注册到容器
 * <br>作 者: zhaoc
 * <br>创 建: 2015年8月16日
 * <br>版 本: v1.0.0
 * <br>
 * <br>历 史: (版本) 作者 时间 注释 
 */
public class ParseBasePackage {
	
	static ParseBasePackage basePackage = null;
	
	/** 是否启用子目录扫描功能 */
	private boolean scanSub = true;
	
	/** 原始包路径 */
	private String originalPath = null;
	
	/** 容器上下文 */
	private ApplicationContext context = XmlApplicationContext.getContainer();;

	public static ParseBasePackage register(String packagePath) {
		return register(packagePath, true);
	}
	
	public static ApplicationContext buildPackagePathApplication(String packagePath) {
		return register(packagePath).getApplicationContext();
	}
	public static ApplicationContext buildPackagePathApplication(String packagePath, boolean scanSub) {
		return register(packagePath, scanSub).getApplicationContext();
	}
	public static ParseBasePackage register(String packagePath, boolean sub) {
		basePackage = new ParseBasePackage(packagePath, sub);
		return basePackage;
	}

	private ParseBasePackage(String path, boolean scanSub) {
		if (path == null || path.indexOf(".") < 0) {
			System.out.println("此处有异常抛出");
			return;
		}
		this.scanSub = scanSub;
		this.originalPath = path;
		path = path.replace(".", "/");
		File file = new File(Thread.currentThread().getContextClassLoader()
				.getResource(path).getFile());
		scanAndRegister(file);
	}
	
	/**
	 * 完成包扫描功能并将扫描的类注册到容器中
	 * @param directory 初始包路径
	 */
	void scanAndRegister(File directory) {
		new ScanControlPower() {
			@Override
			public void scan(File file, String packageName) {
				File[] files = file.listFiles(); /* 获取路径下所有文件(包含目录结构) */
				for(File f : files) {
					if(f.isDirectory()) {
						if(scanSub) { /* 是否启用子目录递归扫描操作 */
							scan(f, packageName + "." + f.getName()); /* 追加要递归的包路径名 */
						}
					} else {
						if(f.getName().endsWith("class")) {
							String classFullName = packageName + "." + f.getName().substring(0, f.getName().length() - 6); /* 构造类的全限定名 */
							register(classFullName);
						}
					}
				}
			}
			
			String getAnnoName(Class<?> clazz) {
				if(clazz.isAnnotationPresent(Part.class)) {
					return clazz.getAnnotation(Part.class).value();
				}
				return null;
			}
			ScopeTypeEnum getAnnoScope(Class<?> clazz) {
				if(clazz.isAnnotationPresent(Part.class)) {
					return clazz.getAnnotation(Part.class).scope();
				}
				return null;
			}
			/**
			 * 容器注册
			 * @param classFullName 要注册类的全限定名
			 */
			@Override
			public <T> void register(String classFullName) {
				try {
					Class<T> clazz = (Class<T>) this.getClass().getClassLoader().loadClass(classFullName); /* 加载要注册的类，此处加载器实际需要定义 */
					if(!clazz.isInterface()) { 
						String injectName = getAnnoName(clazz) != null ? getAnnoName(clazz) : clazz.getSimpleName(); /* 获得注册名 */
						ScopeTypeEnum type = (getAnnoScope(clazz)!=null ? getAnnoScope(clazz) : ScopeTypeEnum.SINGLETON); /* 注册类型 单例；原型*/
						for(Class<? super T> clazzs : (Class<? super T>[])clazz.getInterfaces()) { /* 类层次结构是否有更好的定义*/
							getApplicationContext().inject(clazzs, injectName, clazz, type);
						}
						getApplicationContext().inject(clazz, injectName, clazz, type); /* 非接口形式注册 */
					}
				} catch (ClassNotFoundException e) {
					System.out.println("class <" + classFullName + "> is not found# could not be loaded");
				}
				
			}
		}.scan(directory, originalPath);
	}
	
	public ApplicationContext getApplicationContext() {
		return this.context;
	}
	
	/**
	 * 完成包扫描及类注册的功能
	 */
	interface ScanControlPower {
		
		/**
		 * 包自动扫描,携带包路径,启用子目录扫描 递归追加包名称
		 * @param file 包路径
		 * @param packageName 包名称
		 */
		void scan(File file, String packageName);
		
		/**
		 * 注册到容器
		 * @param classFullName 要注册类的全限定名
		 */
		<T> void register(String classFullName);
	}
}